#include "Device.h"

DEVICE_T* DEVICE_t;


//************************************
// Method:    	CALCU_SAMA					//< SAMA运算函数
// Programmer:  duan
// Time:		2019/06/27
// Returns:   	bool						//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	float dt					//< 运算周期
// Parameter: 	bool * DI					//< 数字量输入值数组指针
// Parameter: 	bool * DO					//< 数字量输出值数组指针
// Parameter: 	bool * AI					//< 模拟量输入值数组指针
// Parameter: 	bool * AO					//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(DEVICE)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
	/****************变量定义区开始**************/

	int i;
	/*<<<<<定义输入变量>>>>>*/
	bool Open_Ovr;							//< 超驰（联锁）开指令
	bool Close_Ovr;							//< 超驰（联锁）关指令
	bool Open_Allow;						//< 开允许信号
	bool Close_Allow;						//< 关允许信号
	bool MAN_Force;							//< 强制手动
	bool AUTO_Req;							//< 自动请求
	bool Dmd1;								//< 该信号作用于Out1
	bool Dmd2;								//< 该信号作用于Out2
	bool Dmd3;								//< 该信号作用于Out3
	bool Sta_FB1;							//< 输出Out1对应的设备运行状态反馈信号
	bool Sta_FB2;							//< 输出Out2对应的设备运行状态反馈信号
	bool Sta_FB3;							//< 设备处于就地状态
	bool Trip_Sig;							//< 跳闸输入信号
	/*<<<<<定义输出变量>>>>>*/
	bool Open_Out;							//< 开指令输出
	bool Close_Out;							//< 关指令输出
	bool Stop_Out;							//< 停止指令输出
	bool MAN_Sta;							//< 手动指示
	bool AUTO_Sta;							//< 自动指示
	bool Device_Sta;						//< 设备状态
	bool Device_FL;							//< 设备故障
	bool Trip_Sta;							//< 跳闸状态
	bool OP_Fail;							//< 操作失败
	/*<<<<<定义参数变量>>>>>*/
	Device_OutMode Out_Mode;
	int OutSig_SetTime;
	int OutSig_RseTime;
	Device_DefaultMode Def_Mode;
	Device_STP STP;

	//< duan 0627 下面三个变量可以定义为枚举类型
	int MP;									//< 手动优先级
	bool FLB;								//< 故障闭锁定义参数
	int Tout;								//< 跳闸置位定义参数

	int Tover;								//< 设备行程时间

	/*<<<<<定义中间变量>>>>>*/
	bool* Last_OpenOut;						//< 上一时刻开指令输出
	bool* Last_CloseOut;					//< 上一时刻关指令输出
	bool* Last_StopOut;						//< 上一时刻停指令输出
	bool* Last_DeviceFL;					//< 上一时刻设备故障
	bool* Last_TripSta;						//< 上一时刻跳闸状态
	bool* Last_OPFail;						//< 上一时刻操作失败

	bool* Last_AUTOReq;						//< 上一时刻自动请求
	bool* Last_OpenOvr;						//< 上一时刻超驰（联锁）开指令
	bool* Last_CloseOvr;					//< 上一时刻超驰（联锁）关指令
	bool* Last_TripSig;						//< 上一时刻跳闸输入信号
	bool* Last_StaFB3;						//< 上一时刻设备处于就地状态
	bool* Last_StaFB1;						//< 输出Out1对应的设备运行状态反馈信号
	bool* Last_StaFB2;						//< 输出Out2对应的设备运行状态反馈信号

	float* OP_Time;
	float* Out_Time;
	Device_AM* Manual;
	bool* Opening;
	bool* Closing;
	bool* Stopping;

	bool* S[3];
	bool* R[3];

	bool* Last_Run;
	bool* Finished;
	bool* Counting;
	bool* OPting;
	float* Counter;
	float* Count;

	bool* Out_Sta[3];
	/****************变量定义区结束**************/

	NAME(DEVICE)* Obj = (NAME(DEVICE)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	Open_Ovr = DI[0];
	Close_Ovr = DI[1];
	Open_Allow = DI[2];
	Close_Allow = DI[3];
	MAN_Force = DI[4];
	AUTO_Req = DI[5];
	Dmd1 = DI[6];
	Dmd2 = DI[7];
	Dmd3 = DI[8];
	Sta_FB1 = DI[9];
	Sta_FB2 = DI[10];
	Sta_FB3 = DI[11];
	Trip_Sig = DI[12];

	/*<<<<<参数变量赋值>>>>>*/
	Out_Mode = Obj->Par.Out_Mode;
	OutSig_SetTime = Obj->Par.OutSig_SetTime;
	OutSig_RseTime = Obj->Par.OutSig_RseTime;
	Def_Mode = Obj->Par.Def_Mode;
	STP = Obj->Par.STP;
	MP = Obj->Par.MP;
	FLB = Obj->Par.FLB;
	Tout = Obj->Par.Tout;

	Tover = Obj->Par.Tover;

	/*<<<<<中间变量赋值>>>>>*/
	Last_OpenOut = &(Obj->Sta.Last_OpenOut);
	Last_CloseOut = &(Obj->Sta.Last_CloseOut);
	Last_StopOut = &(Obj->Sta.Last_StopOut);
	Last_DeviceFL = &(Obj->Sta.Last_DeviceFL);
	Last_TripSta = &(Obj->Sta.Last_TripSta);
	Last_OPFail = &(Obj->Sta.Last_OPFail);

	Last_AUTOReq = &(Obj->Sta.Last_AUTOReq);
	Last_OpenOvr = &(Obj->Sta.Last_OpenOvr);
	Last_CloseOvr = &(Obj->Sta.Last_CloseOvr);
	Last_TripSig = &(Obj->Sta.Last_TripSig);
	Last_StaFB3 = &(Obj->Sta.Last_StaFB3);
	Last_StaFB1 = &(Obj->Sta.Last_StaFB2);
	Last_StaFB2 = &(Obj->Sta.Last_StaFB1);

	OP_Time = &(Obj->Sta.OP_Time);
	Out_Time = &(Obj->Sta.Out_Time);
	Manual = &(Obj->Sta.Manual);
	Opening = &(Obj->Sta.Opening);
	Closing = &(Obj->Sta.Closing);
	Stopping = &(Obj->Sta.Stopping);

	Last_Run = &(Obj->Sta.Last_Run);
	Finished = &(Obj->Sta.Finished);
	Counting = &(Obj->Sta.Counting);
	OPting = &(Obj->Sta.OPting);
	Counter = &(Obj->Sta.Counter);
	Count = &(Obj->Sta.Count);

	for (i = 0; i < 3; i++)
	{
		Out_Sta[i] = &(Obj->Sta.Out_Sta[i]);
		S[i] = &(Obj->Sta.S[i]);
		R[i] = &(Obj->Sta.R[i]);
	}



	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/
	if (Count[0] == 0)
	{
		if (Def_Mode == Def_MAN)
			Manual[0] = Device_MAN;
		else
			Manual[0] = Device_AUTO;
	}

	if (Sta_FB1 == true && Sta_FB2 == true)
		Device_FL = true;
	else
		Device_FL = false;

	if (Sta_FB3 == false && Counting[0] == 0)
	{
		switch (Tout)
		{
		case 0:
			if (Last_StaFB2[0] != Sta_FB2)
				Trip_Sta = true;
			break;
		case 1:
			if (Last_StaFB1[0] != Sta_FB1)
				Trip_Sta = true;
			break;
		case 2:
			if (Last_StaFB2[0] != Sta_FB2|| Last_StaFB1[0] != Sta_FB1)
				Trip_Sta = true;
			break;
		default:
			break;
		}
	}

	if (MAN_Force == true)
		Manual[0] = Device_MAN;

	if (Sta_FB3 == false)
	{
		if (Device_FL == false && FLB == true)
		{
			if (Tout == 2 || Trip_Sig == false)
			{
				if (Trip_Sta == false || FLB == true)
				{
					if (OP_Fail == false || FLB == false)
					{
						if (Open_Ovr == false && Close_Ovr == false)
						{
							if (Count[0] != 0 && AUTO_Req == true && Last_AUTOReq[0] == false && MAN_Force == false)
								Manual[0] = Device_AUTO;

							if (Manual[0] == Device_AUTO)
							{
								if (Dmd1 == true && Open_Allow == true)
								{
									if (((STP == 2 || STP == 3) && Last_Run[0] == 0) || STP == 0 || STP == 1 || STP == 4 || STP == 5)
									{
										if (Sta_FB1 == false || Out_Mode == PulseSin_FB || Out_Mode == PulseSeq_FB || Out_Mode == LongSig_FB || Out_Mode == LongSig_OD)
										{
											Opening[0] = true;
											Close_Out = false;
											Stop_Out = false;
											Finished[0] = false;
											Stopping[0] = false;
										}

										if (Closing[0] == true)
										{
											if (STP == 4 || STP == 5)
											{
												Stop_Out = true;
												Opening[0] = false;
												OPting[0] = false;
												Counting[0] = false;
											}
											Close_Out = false;
											Counter[0] = 0;
											Closing[0] = false;
											Last_Run[0] = false;
											OP_Time[0] = 0;
											Finished[0] = false;
											Out_Time[0] = 0;
										}
									}
								}

								if (Dmd2 == true && Close_Allow == true)
								{
									if (((STP == 2 || STP == 3) && Last_Run[0] == 0) || STP == 0 || STP == 1 || STP == 4 || STP == 5)
									{
										if (Sta_FB2 == false || Out_Mode == PulseSin_FB || Out_Mode == PulseSeq_FB || Out_Mode == LongSig_FB || Out_Mode == LongSig_OD)
										{
											Closing[0] = true;
											Open_Out = false;
											Stop_Out = false;
											Finished[0] = false;
											Stopping[0] = false;
										}

										if (Opening[0] == true)
										{
											if (STP == 4 || STP == 5)
											{
												Stop_Out = true;
												Closing[0] = false;
												OPting[0] = false;
												Counting[0] = false;
											}
											Open_Out = false;
											OP_Time[0] = 0;
											Opening[0] = false;
											Last_Run[0] = false;
											Finished[0] = false;
											Out_Time[0] = 0;
										}
									}
								}

								if (Dmd3 == true)
								{
									if (STP == 1 || STP == 3 || STP == 5)
									{
										Open_Out = false;
										Close_Out = false;
										Stop_Out = true;

										Stopping[0] = true;
										Opening[0] = false;
										Closing[0] = false;

										Counting[0] = false;
										OPting[0] = false;

										OP_Time[0] = 0;
										Out_Time[0] = 0;

									}
								}
							}
						}

						else if (Open_Ovr == true)
						{
							if (Last_OpenOvr[0] == false && Open_Ovr == true && MAN_Force == false)
								Manual[0] = (Device_AM)Def_Mode;

							if (Manual[0] == Device_AUTO)
							{
								AUTO_Sta = true;
								MAN_Sta = false;
							}
							else
							{
								AUTO_Sta = false;
								MAN_Sta = true;
							}

							Close_Out = false;
							Stop_Out = false;

							Opening[0] = true;
							Stopping[0] = false;
							Finished[0] = false;

							if (Closing[0] == true)
							{
								Closing[0] = false;
								Last_Run[0] = false;

								OP_Time[0] = 0;
								Out_Time[0] = 0;
								Counter[0] = 0;
							}
						}

						else if (Close_Ovr == true)
						{
							if (Last_CloseOvr[0] == false && Close_Ovr == true && MAN_Force == false)
								Manual[0] = (Device_AM)Def_Mode;

							if (Manual[0] == Device_AUTO)
							{
								AUTO_Sta = true;
								MAN_Sta = false;
							}
							else
							{
								AUTO_Sta = false;
								MAN_Sta = true;
							}

							Open_Out = false;
							Stop_Out = false;

							Closing[0] = true;
							Stopping[0] = false;
							Finished[0] = false;

							if (Opening[0] == true)
							{
								Opening[0] = false;
								Last_Run[0] = false;

								OP_Time[0] = 0;
								Out_Time[0] = 0;
							}
						}
					}

					else
					{
						Open_Out = false;
						Close_Out = false;
						if (STP == 1 || STP == 3 || STP == 5)
							Stop_Out = true;
						Opening[0] = false;
						Closing[0] = false;
						Counting[0] = false;
						OPting[0] = false;

						Counter[0] = 0;
						OP_Time[0] = 0;
						Out_Time[0] = 0;
					}
				}

				else
				{
					if (Last_TripSta[0] == false && Trip_Sta == true && MAN_Force == false)
						Manual[0] = (Device_AM)Def_Mode;

					if (Manual[0] == Device_AUTO)
					{
						AUTO_Sta = true;
						MAN_Sta = false;
					}
					else
					{
						AUTO_Sta = false;
						MAN_Sta = true;
					}

					Open_Out = false;
					Close_Out = false;

					Opening[0] = false;
					Closing[0] = false;
					Counting[0] = false;
					OPting[0] = false;
					Counter[0] = 0;
					OP_Time[0] = 0;
					Out_Time[0] = 0;
				}
			}

			else
			{
				Trip_Sta = true;

				if (Trip_Sig == true && Last_TripSig[0] == false && MAN_Force == false)
					Manual[0] = (Device_AM)Def_Mode;

				if (Manual[0] == Device_AUTO)
				{
					AUTO_Sta = true;
					MAN_Sta = false;
				}
				else
				{
					AUTO_Sta = false;
					MAN_Sta = true;
				}

				if (Tout == 0)
				{
					Open_Out = false;
					Stop_Out = false;

					Closing[0] = true;
					Stopping[0] = false;

					if (Opening[0] == true)
					{
						Opening[0] = false;
						Counter[0] = 0;
						OP_Time[0] = 0;
						Out_Time[0] = 0;
					}
				}
				else if (Tout == 1)
				{
					Close_Out = false;
					Stop_Out = false;
					Opening[0] = true;
					Stopping[0] = false;

					if (Closing[0] == true)
					{
						Closing[0] = false;
						Counter[0] = 0;
						OP_Time[0] = 0;
						Out_Time[0] = 0;
					}
				}
			}
		}

		else
		{
			Open_Out = false;
			Close_Out = false;
			if (STP == 1 || STP == 3 || STP == 5)
				Stop_Out = true;
			Opening[0] = false;
			Closing[0] = false;
			Counting[0] = false;
			OPting[0] = false;

			Counter[0] = 0;
			OP_Time[0] = 0;
			Out_Time[0] = 0;

			if (Last_DeviceFL[0] == false && Device_FL == true && MAN_Force == false)
				Manual[0] = (Device_AM)Def_Mode;

			if (Manual[0] == Device_AUTO)
			{
				AUTO_Sta = true;
				MAN_Sta = false;
			}
			else
			{
				AUTO_Sta = false;
				MAN_Sta = true;
			}
		}
	}

	else
	{
		Open_Out = false;
		Close_Out = false;
		if (STP == 1 || STP == 3 || STP == 5)
			Stop_Out = true;
		Opening[0] = false;
		Closing[0] = false;
		Counting[0] = false;
		OPting[0] = false;

		Counter[0] = 0;
		OP_Time[0] = 0;
		Out_Time[0] = 0;

		if (Last_StaFB3[0] == false && Sta_FB3 == true && MAN_Force == false)
			Manual[0] = (Device_AM)Def_Mode;

		if (Manual[0] == Device_AUTO)
		{
			AUTO_Sta = true;
			MAN_Sta = false;
		}
		else
		{
			AUTO_Sta = false;
			MAN_Sta = true;
		}
	}

	if (Opening[0] == true)
	{
		int Cmd = 1;
		if (Out_Mode == PulseSin_FB_Res || Out_Mode == PulseSeq_FB_Res || Out_Mode == LongSig_FB_Res || Out_Mode == LongSig_OD_Res)
		{
			S[1][0] = Opening[0] && (!Sta_FB1);
			R[1][0] = Stopping[0] || Sta_FB1 || Closing[0];

			if (R[1][0] == true)
			{
				Open_Out = false;
				Stop_Out = true;

				Opening[0] = false;
				Counting[0] = false;
				Finished[0] = false;

				OP_Time[0] = 0;
				Counter[0] = 0;
			}
		}

		if (Out_Mode != PulseSin_FB_Res && Out_Mode != PulseSeq_FB_Res && Out_Mode != LongSig_FB_Res && Out_Mode != LongSig_OD_Res)
		{
			if (Out_Mode == PulseSin_FB_NORes || Out_Mode == PulseSeq_FB_NORes || Out_Mode == LongSig_FB_NORes || Out_Mode == LongSig_OD_NORes)
			{
				S[2][0] = Opening[0] && (!Sta_FB1);
				R[2][0] = Closing[0] || Stopping;
				if (R[2][0] == true)
				{
					Open_Out = false;
					
					Opening[0] = false;
					Counting[0] = false;
					OPting[0] = false;
				
					OP_Time[0] = 0;
					Out_Time[0] = 0;
					Counter[0] = 0;
				}
			}
			else
			{
				S[2][0] = 1;
				R[2][0] = Stopping[0] || Closing[0];
				if (R[2][0] == 1)
				{
					Open_Out = false;

					Opening[0] = false;
					Counting[0] = false;
					OPting[0] = false;

					OP_Time[0] = 0;
					Out_Time[0] = 0;
					Counter[0] = 0;
				}

			}

			if (Out_Mode != LongSig_OD_Res && Out_Mode != LongSig_OD_NORes && Out_Mode != LongSig_OD)
			{
				if (OPting[0] == true)
				{
					if (Out_Time[0] < Tover)
						Out_Time[0] += dt;
				}
			}

		}

		if (Sta_FB1 == true)
		{
			OP_Time[0] = 0;
			Counting[0] = 0;
		}

		if (R[1][0] == false && S[1][0] == true)
			Out_Sta[1][0] = true;
		if (R[1][0] == true)
			Out_Sta[1][0] = false;
		if (R[2][0] == false && S[2][0] == true)
			Out_Sta[2][0] = true;
		if (R[2][0] == true)
			Out_Sta[2][0] = false;

		if (Out_Mode == PulseSin_FB_Res || Out_Mode == PulseSeq_FB_Res || Out_Mode == LongSig_FB_Res || Out_Mode == LongSig_OD_Res)
			Out_Sta[2][0] = false;
		else
			Out_Sta[1][0] = false;

		if (Out_Sta[1][0] == true || Out_Sta[2][0] == true)
		{
			switch (Out_Mode)
			{
			case 0:
			case 4:
			case 8:
			{
				if (Out_Mode == PulseSin_FB && Finished[0] == true)
					Finished[0] = false;
				if (Counter[0] <= OutSig_SetTime)
				{
					if (Cmd == 1 && Finished[0] == false)
					{
						Open_Out = true;
						Counter[0] += dt;
					}
					else if (Finished[0] == false)
					{
						Close_Out = true;
						Counter[0] += dt;
					}
				}
				else if (Cmd == 1)
				{
					Finished[0] = true;
					Open_Out = false;
					Counter[0] = false;
				}
				else
				{
					Finished[0] = true;
					Close_Out = false;
					Counter[0] = 0;
				}
			}
				break;

			case 1:
			case 5:
			case 9:
			{
				if (OutSig_RseTime == 0)
					OutSig_RseTime = OutSig_SetTime / 2;
				if (Counter[0] <= OutSig_SetTime)
				{
					if (Cmd == 1)
					{
						Open_Out = true;
						Counter[0] += dt;
					}
					else
					{
						Close_Out = true;
						Counter[0] += dt;
					}
				}
				else if (Counter[0] > OutSig_SetTime&&Counter[0] < OutSig_SetTime + OutSig_RseTime)
				{
					if (Cmd == 1)
					{
						Open_Out = false;
						Counter[0] += dt;
					}
					else
					{
						Close_Out = false;
						Counter[0] += dt;
					}
				}
				else
					Counter[0] = 0;	
			}
				break;

			case 2:
			case 6:
			case 10:
			case 3:
			case 7:
			case 11:
			{
				if (Cmd == 1)
					Open_Out = true;
				else
					Close_Out = true;
			}
				break;

			default:
				break;
			}
		}
	}

	else if (Closing[0] == true)
	{
		int Cmd = 0;
		if (Out_Mode == PulseSin_FB_Res || Out_Mode == PulseSeq_FB_Res || Out_Mode == LongSig_FB_Res || Out_Mode == LongSig_OD_Res)
		{
			S[1][0] = Closing[0] && (!Sta_FB2);
			R[1][0] = Stopping[0] || Sta_FB2 || Opening[0];
			if (R[1][0] == true)
			{
				Closing[0] = false;
				Counting[0] = false;
				Finished[0] = false;

				Close_Out = false;
				Stop_Out = true;

				OP_Time[0] = 0;
				Counter[0] = 0;
			}
		}

		if (Out_Mode != PulseSin_FB_Res && Out_Mode != PulseSeq_FB_Res && Out_Mode != LongSig_FB_Res && Out_Mode != LongSig_OD_Res)
		{
			if (Out_Mode == PulseSin_FB_NORes || Out_Mode == PulseSeq_FB_NORes || Out_Mode == LongSig_FB_NORes || Out_Mode == LongSig_OD_NORes)
			{
				S[2][0] = Closing[0] && (!Sta_FB2);
				R[2][0] = Opening[0] || Stopping[0];
				if (R[2][0] == true)
				{
					Closing[0] = false;
					Counting[0] = false;
					OPting[0] = false;

					OP_Time[0] = 0;
					Counter[0] = 0;
					Out_Time[0] = 0;

					Close_Out = false;
				}
			}

			else
			{
				S[2][0] = true;
				R[2][0] = Opening[0] || Stopping[0];
				if (R[2][0] == true)
				{
					Closing[0] = false;
					Counting[0] = false;
					OPting[0] = false;

					OP_Time[0] = 0;
					Out_Time[0] = 0;
					Counter[0] = 0;

					Close_Out = false;
				}
			}

			if (Out_Mode != LongSig_OD_Res && Out_Mode != LongSig_OD_NORes && Out_Mode != LongSig_OD)
			{
				if (OPting[0] == true)
				{
					if (Out_Time[0] < Tover)
						Out_Time[0] += dt;
				}
			}
		}

		if (Sta_FB2 == true)
		{
			OP_Time[0] = false;
			Counting[0] = false;
		}

		if (R[1][0] == false && S[1][0] == true)
			Out_Sta[1][0] = true;
		if (R[1][0] == true)
			Out_Sta[1][0] = false;
		if (R[2][0] == false && S[2][0] == true)
			Out_Sta[2][0] = true;
		if (R[2][0] == true)
			Out_Sta[2][0] = false;

		if (Out_Mode == PulseSin_FB_Res || Out_Mode == PulseSeq_FB_Res || Out_Mode == LongSig_FB_Res || Out_Mode == LongSig_OD_Res)
			Out_Sta[2][0] = false;
		else
			Out_Sta[1][0] = false;

		if (Out_Sta[1][0] == true || Out_Sta[2][0] == true)
		{
			switch (Out_Mode)
			{
				case 0:
				case 4:
				case 8:
				{
					if (Out_Mode == PulseSin_FB && Finished[0] == true)
						Finished[0] = false;
					if (Counter[0] <= OutSig_SetTime)
					{
						if (Cmd == 1 && Finished[0] == false)
						{
							Open_Out = true;
							Counter[0] += dt;
						}
						else if (Finished[0] == false)
						{
						Close_Out = true;
						Counter[0] += dt;
						}
					}
					else if (Cmd == 1)
					{
						Finished[0] = true;
						Open_Out = false;
						Counter[0] = 0;
					}
					else
					{
					Finished[0] = true;
					Close_Out = false;
					Counter[0] = 0;
					}
				}
					break;

				case 1:
				case 5:
				case 9:
				{
					if (OutSig_RseTime == 0)
						OutSig_RseTime = OutSig_SetTime / 2;
					if (Counter[0] <= OutSig_SetTime)
					{
						if (Cmd == 1)
						{
							Open_Out = true;
							Counter[0] += dt;
						}
						else
						{
							Close_Out = true;
							Counter[0] += dt;
						}
					}
					else if (Counter[0] > OutSig_SetTime&&Counter[0] < OutSig_SetTime + OutSig_RseTime)
					{
						if (Cmd == 1)
						{
							Open_Out = false;
							Counter[0] += dt;
						}
						else
						{
							Close_Out = false;
							Counter[0] += dt;
						}
					}
					else
						Counter[0] = false;
				}
					break;

				case 2:
				case 6:
				case 10:
				case 3:
				case 7:
				case 11:
				{
					if (Cmd == 1)
						Open_Out = true;
					else
						Close_Out = true;
				}
					break;

				default:
					break;
			}
		}
	}

	if (Sta_FB1 == true)
		Device_Sta = true;
	else if (Sta_FB2 == true)
		Device_Sta = false;
	else if (Sta_FB1 == true && Sta_FB2 == true)
		Device_Sta = false;

	if (Tover == 0)
		Tover = 5;
	if (Tover < OutSig_SetTime)
		Tover = OutSig_SetTime;

	if ((Opening[0] == true || Closing[0] == true) && Last_Run[0] == false)
	{
		if (Out_Mode == PulseSin_FB_NORes || Out_Mode == PulseSeq_FB_NORes || Out_Mode == LongSig_FB_NORes || Out_Mode == PulseSin_FB || Out_Mode == PulseSeq_FB || Out_Mode == LongSig_FB)
			OPting[0] = true;
		Counting[0] = true;
	}

	if (Counting[0] == true)
	{
		if (OP_Time[0] > Tover&&Out_Mode != LongSig_OD_Res && Out_Mode != LongSig_OD_NORes && Out_Mode != LongSig_OD)
		{
			if (Last_OPFail[0] == false)
				Manual[0] = (Device_AM)Def_Mode;
			Counting[0] = false;
			OP_Time[0] = 0;
			OP_Fail = true;
			OPting[0] = false;
			Out_Time[0] = 0;
		}
		else
			OP_Time[0] += dt;
	}

	if (Manual[0] = Device_AUTO)
	{
		AUTO_Sta = true;
		MAN_Sta = false;
	}
	else
	{
		AUTO_Sta = false;
		MAN_Sta = true;
	}

	Last_Run[0] = Opening[0] || Closing[0];

	if (Count[0] < 10)
		Count[0] += 1;


	Last_OpenOut[0] = Open_Out;
	Last_CloseOut[0] = Close_Out;
	Last_StopOut[0] = Stop_Out;
	Last_DeviceFL[0] = Device_FL;
	Last_TripSta[0] = Trip_Sta;
	Last_OPFail[0] = OP_Fail;

	Last_AUTOReq[0] = AUTO_Req;
	Last_OpenOvr[0] = Open_Ovr;
	Last_CloseOvr[0] = Close_Ovr;
	Last_TripSig[0] = Trip_Sig;
	Last_StaFB3[0] = Sta_FB3;
	Last_StaFB1[0] = Sta_FB1;
	Last_StaFB2[0] = Sta_FB2;

	/**************算法功能实现结束**************/
	/********************************************/
	/****************运算结果输出**************/
	Open_Out = DO[0];
	Close_Out = DO[1];
	Stop_Out = DO[2];
	MAN_Sta = DO[3];
	AUTO_Sta = DO[4];
	Device_Sta = DO[5];
	Device_FL = DO[6];
	Trip_Sta = DO[7];
	OP_Fail = DO[8];

	/**************运算结果输出完毕************/
	return true;
}



//************************************
// Method:    	BCPARA						//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  duan
// Time:		2019/06/12
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	void ** Data				//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(DEVICE)(Model_Base_t* arg, void** Data)
{
	NAME(DEVICE)* Obj = (NAME(DEVICE)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA						//< 备份SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/12
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 指定模块类型链表的指针
// Parameter: 	void ** Data				//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(DEVICE)(Model_Base_t* arg, void** Data)
{
	NAME(DEVICE)* Obj = (NAME(DEVICE)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA							//< 解析备份的SAMA运算中间参数
// Programmer:  duan
// Time:		2019/06/12
// Returns:   	int								//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(DEVICE)(Model_Base_t* arg, void** Data)
{
	NAME(DEVICE)* Obj = (NAME(DEVICE)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR					//< 在线修改模块参数函数
// Programmer:  duan
// Time:		2019/06/12
// Returns:   	int							//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg			//< 指定模块类型链表的指针
// Parameter: 	void** Data					//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(DEVICE)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(DEVICE)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR					//< 初始化模块运算中间参数
// Programmer:  duan
// Time:		2019/06/12
// Parameter: 	Model_Base_t* arg			//< 模块参数结构体指针
//************************************
void INIT_STAPAR(DEVICE)(Model_Base_t* arg)
{
	NAME(DEVICE)* name = (NAME(DEVICE)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/

	/**************对中间变量结构体的相关参数进行赋值结束************/
}



//************************************
// Method:    	CMD_DEAL					//< 与模块相关的命令字处理函数
// Programmer:  duan
// Time:		2019/06/12
// Returns:   	void					
// Parameter: 	Model_Base_t* arg			//< 指定模块类型链表的指针
// Parameter: 	void* Data					//< 信息头指针
// Parameter: 	char* CMD					//< 命令字
//************************************
void CMD_DEAL(DEVICE)(Model_Base_t* arg, void* Data, const char* CMD)
{
#define	MEMREAD1(var)	MEMREAD(var, Data)

}


